package org.ciallo.simplemusicplayer.controller;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import androidx.annotation.Nullable;
import org.ciallo.simplemusicplayer.data.model.Song;
import org.ciallo.simplemusicplayer.service.MediaPlayerService;
import org.ciallo.simplemusicplayer.util.Constants;
import timber.log.Timber;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Jukomu
 * @Description: 播放控制器类
 * 负责与 MediaPlayerService 绑定，并向其发送播放控制指令。
 * 它不再直接观察 LiveData 或通过回调更新UI，这些职责转移到 ViewModel 和 UI 组件本身。
 * @Package: org.ciallo.simplemusicplayer.controller
 * @Project: SimpleMusicPlayer
 * @name: PlayerController
 * @Date: 2025/5/27-02:12
 * @Filename: PlayerController
 */
public class PlayerController {

    private Context applicationContext;               // 应用上下文，用于启动/绑定服务
    private MediaPlayerService musicService;          // MediaPlayerService的实例引用
    private boolean isServiceBound = false;           // 标记服务是否已绑定
    // PlayerUIListener uiListener;              // 不再需要，UI直接观察Service的LiveData

    /**
     * PlayerController的构造函数。
     *
     * @param context 应用上下文 (通常是 ApplicationContext)。
     */
    public PlayerController(Context context) {
        // 使用 ApplicationContext 防止 Activity/Fragment 泄漏
        this.applicationContext = context.getApplicationContext();
        bindToService(); // 初始化时绑定到MediaPlayerService
    }

    /**
     * 绑定到 MediaPlayerService。
     */
    private void bindToService() {
        if (applicationContext == null) {
            Timber.e("ApplicationContext is null in bindToService. Controller might not have been properly initialized.");
            return;
        }
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        // 确保服务已启动，以便在后台持续运行
        applicationContext.startService(intent);
        applicationContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * ServiceConnection的实现，用于处理与MediaPlayerService的连接状态。
     */
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
            musicService = binder.getService(); // 获取Service实例
            isServiceBound = true;
            Timber.d("PlayerController connected to MediaPlayerService.");

            // 服务连接后，不需要立即通过 uiListener 更新UI，因为UI会直接观察LiveData
            // 但可以触发一次PlaybackInfo的更新（如果Service内部逻辑允许或有意义）
            // 例如，让Service重新广播一次当前状态，确保新连接的Controller（如果UI重建）能立即获取
            if (musicService != null) {
                // 可以在Service中添加一个方法来重新广播当前状态，或者依赖LiveData的粘性行为（如果适用）
                // MediaPlayerService.PlaybackInfo currentInfo = MediaPlayerService.playbackInfo.getValue();
                // if (currentInfo != null && uiListener != null) { ... } // 这部分已移除
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isServiceBound = false;
            musicService = null; // 清除Service引用
            Timber.w("PlayerController unexpectedly disconnected from MediaPlayerService.");
            // 可以在这里处理服务断开的逻辑，例如通过 SharedViewModel 通知UI
            // if (uiListener != null) { uiListener.onError("播放服务已断开"); } // uiListener已移除
        }
    };

    /**
     * 请求播放指定索引的歌曲，并设置新的播放列表。
     *
     * @param playQueue  要设置的新播放列表。
     * @param startIndex 要开始播放的歌曲在列表中的索引。
     */
    public void playSongAtIndex(List<Song> playQueue, int startIndex) {
        if (applicationContext == null) {
            Timber.e("ApplicationContext is null.");
            return;
        }
        if (playQueue == null || playQueue.isEmpty()) {
            Timber.w("Play queue is empty or null.");
            return;
        }
        if (startIndex < 0 || startIndex >= playQueue.size()) {
            Timber.w("Invalid start index %d for queue size %d. Defaulting to 0.", startIndex, playQueue.size());
            startIndex = 0;
        }

        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_PLAY_SONG_AT_INDEX);
        intent.putParcelableArrayListExtra(Constants.EXTRA_PLAY_QUEUE, new ArrayList<>(playQueue)); // 传递副本
        intent.putExtra(Constants.EXTRA_START_INDEX, startIndex);
        applicationContext.startService(intent);
        Timber.d("playSongAtIndex command sent. Index: %d, Queue size: %d", startIndex, playQueue.size());
    }

    /**
     * 请求播放一首新歌（将这首歌作为新的单曲播放列表）。
     *
     * @param song 要播放的歌曲对象。
     */
    public void playNewSong(Song song) {
        if (applicationContext == null) {
            Timber.e("ApplicationContext is null.");
            return;
        }
        if (song != null) {
            List<Song> singleSongQueue = new ArrayList<>();
            singleSongQueue.add(song);
            playSongAtIndex(singleSongQueue, 0);
            Timber.d("playNewSong command sent for: %s", song.getTitle());
        } else {
            Timber.w("Song object is null in playNewSong.");
        }
    }

    /**
     * 请求切换播放/暂停状态。
     */
    public void togglePlayPause() {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_TOGGLE_PLAY_PAUSE);
        applicationContext.startService(intent);
        Timber.d("togglePlayPause command sent.");
    }

    /**
     * 请求播放下一首歌曲。
     */
    public void playNext() {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_NEXT_SONG);
        applicationContext.startService(intent);
        Timber.d("playNext command sent.");
    }

    /**
     * 请求播放上一首歌曲。
     */
    public void playPrevious() {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_PREVIOUS_SONG);
        applicationContext.startService(intent);
        Timber.d("playPrevious command sent.");
    }

    /**
     * 请求跳转到歌曲的指定播放位置。
     *
     * @param position 目标播放位置 (毫秒)。
     */
    public void seekTo(long position) {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_SEEK_TO);
        intent.putExtra(Constants.EXTRA_SEEK_POSITION, position);
        applicationContext.startService(intent);
        Timber.d("seekTo command sent, position: %dms", position);
    }

    /**
     * 设置播放模式。
     *
     * @param playMode 要设置的播放模式 (参考 Constants.PLAY_MODE_*)。
     */
    public void setPlayMode(int playMode) {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_SET_PLAY_MODE);
        intent.putExtra(Constants.EXTRA_PLAY_MODE, playMode);
        applicationContext.startService(intent);
        Timber.d("setPlayMode command sent. Mode: %d", playMode);
    }

    /**
     * 循环切换到下一个播放模式。
     */
    public void cyclePlayMode() {
        if (applicationContext == null) {
            Timber.e("ApplicationContext is null.");
            return;
        }
        MediaPlayerService.PlaybackInfo currentInfo = MediaPlayerService.playbackInfo.getValue();
        int currentMode = (currentInfo != null) ? currentInfo.playMode : Constants.PLAY_MODE_ORDER;
        int nextMode = (currentMode + 1) % Constants.PLAY_MODE_COUNT;
        setPlayMode(nextMode);
        Timber.d("Cycling play mode from %d to %d", currentMode, nextMode);
    }

    /**
     * 从当前播放队列中移除指定的歌曲。
     *
     * @param songId 要移除的歌曲的ID。
     */
    public void removeSongFromQueue(long songId) {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_REMOVE_SONG_FROM_QUEUE);
        intent.putExtra(Constants.EXTRA_SONG_ID_TO_REMOVE, songId);
        applicationContext.startService(intent);
        Timber.d("removeSongFromQueue command sent. Song ID: %d", songId);
    }

    /**
     * 清空当前播放队列。
     */
    public void clearQueue() {
        if (applicationContext == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_CLEAR_QUEUE);
        applicationContext.startService(intent);
        Timber.d("clearQueue command sent.");
    }

    /**
     * 请求播放当前队列中具有指定ID的歌曲。
     *
     * @param songId 要播放的歌曲的ID。
     */
    public void playSongByIdInCurrentQueue(long songId) {
        if (applicationContext == null) {
            Timber.e("ApplicationContext is null.");
            return;
        }
        if (songId == Constants.INVALID_INDEX || songId == 0) { // 使用 INVALID_INDEX
            Timber.w("Invalid songId provided to playSongByIdInCurrentQueue: %d", songId);
            return;
        }
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_PLAY_SPECIFIC_SONG_ID_IN_QUEUE);
        intent.putExtra(Constants.EXTRA_SONG_ID, songId);
        applicationContext.startService(intent);
        Timber.d("playSongByIdInCurrentQueue command sent. Song ID: %d", songId);
    }

    /**
     * 释放资源，主要是解绑与MediaPlayerService的连接。
     * 这个方法应该在持有此 PlayerController 的组件 (如 SharedViewModel) 的生命周期结束时调用。
     */
    public void release() {
        Timber.d("Releasing PlayerController resources (unbinding service).");
        if (applicationContext != null && isServiceBound) {
            try {
                applicationContext.unbindService(serviceConnection);
            } catch (IllegalArgumentException e) {
                Timber.w(e, "Service was not registered or already unbound during PlayerController release.");
            }
            isServiceBound = false;
        }
        musicService = null;
        // applicationContext = null; // ApplicationContext 通常不需要在这里置空
        Timber.d("PlayerController resources released status: isServiceBound=%b", isServiceBound);
    }

    /**
     * 获取当前播放信息。
     * 主要用于调试或某些需要立即获取快照值的场景。UI更新应优先观察LiveData。
     *
     * @return 当前的PlaybackInfo。
     */
    @Nullable
    public MediaPlayerService.PlaybackInfo getCurrentPlaybackInfo() {
        return MediaPlayerService.playbackInfo.getValue();
    }

    /**
     * 检查服务是否已绑定。
     *
     * @return 如果服务已绑定则返回 true，否则返回 false。
     */
    public boolean isServiceBound() {
        return isServiceBound;
    }

    /**
     * 获取 MediaPlayerService 的实例。
     * 警告：直接暴露 Service 实例可能破坏封装，应谨慎使用。
     * 最好是通过 PlayerController 的方法来间接与 Service 交互。
     *
     * @return MediaPlayerService 实例，如果未绑定则返回 null。
     */
    @Nullable
    public MediaPlayerService getMusicService() {
        if (isServiceBound && musicService != null) {
            return musicService;
        }
        Timber.w("MusicService instance requested from PlayerController but service is not bound or null.");
        return null;
    }

    /**
     * 请求将指定歌曲插入到当前播放歌曲的下一首位置，并在队列为空或播放器空闲时开始播放。
     * @param song 要插入的歌曲。
     */
    public void insertSongAsNext(Song song) {
        if (applicationContext == null || song == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_INSERT_SONG_AS_NEXT_IN_QUEUE);
        intent.putExtra(Constants.EXTRA_SONG_OBJECT, song);
        applicationContext.startService(intent);
        Timber.d("insertSongAsNext command sent for song: %s", song.getTitle());
    }

    /**
     * 请求将指定歌曲添加到当前播放队列的末尾，并在队列为空或播放器空闲时开始播放。
     * @param song 要添加的歌曲。
     */
    public void addSongToEndOfQueue(Song song) {
        if (applicationContext == null || song == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_ADD_SONG_TO_END_OF_QUEUE);
        intent.putExtra(Constants.EXTRA_SONG_OBJECT, song);
        applicationContext.startService(intent);
        Timber.d("addSongToEndOfQueue command sent for song: %s", song.getTitle());
    }

    /**
     * 请求立即播放指定的歌曲。
     * 这可能会替换当前队列或将歌曲插入到当前位置并播放。
     * @param song 要立即播放的歌曲。
     */
    public void playImmediately(Song song) {
        if (applicationContext == null || song == null) return;
        Intent intent = new Intent(applicationContext, MediaPlayerService.class);
        intent.setAction(Constants.ACTION_PLAY_IMMEDIATELY);
        intent.putExtra(Constants.EXTRA_SONG_OBJECT, song);
        applicationContext.startService(intent);
        Timber.d("playImmediately command sent for song: %s", song.getTitle());
    }
}
